home *** CD-ROM | disk | FTP | other *** search
- /*
- (C) 1995-96 AROS - The Amiga Replacement OS
- $Id: matchpattern.c,v 1.1 1996/09/11 12:54:46 digulla Exp $
- $Log: matchpattern.c,v $
- Revision 1.1 1996/09/11 12:54:46 digulla
- A couple of new DOS functions from M. Fleischer
-
- Desc:
- Lang: english
- */
- #include <exec/memory.h>
- #include <clib/exec_protos.h>
- #include <dos/dosextens.h>
- #include "dos_intern.h"
-
- /*****************************************************************************
-
- NAME */
- #include <clib/dos_protos.h>
-
- __AROS_LH2(BOOL, MatchPattern,
-
- /* SYNOPSIS */
- __AROS_LHA(STRPTR, pat, D1),
- __AROS_LHA(STRPTR, str, D2),
-
- /* LOCATION */
- struct DosLibrary *, DOSBase, 141, Dos)
-
- /* FUNCTION
-
- INPUTS
-
- RESULT
-
- NOTES
-
- EXAMPLE
-
- BUGS
-
- SEE ALSO
-
- INTERNALS
-
- HISTORY
- 29-10-95 digulla automatically created from
- dos_lib.fd and clib/dos_protos.h
-
- *****************************************************************************/
- {
- __AROS_FUNC_INIT
- __AROS_BASE_EXT_DECL(struct DosLibrary *,DOSBase)
-
- /*
- A simple method for pattern matching with multiple wildcards:
- I use markers that consist of both a pointer into the string
- and one into the pattern. The marker simply follows the string
- and everytime it hits a wildcard it's split into two new markers
- (one to assume that the wildcard match has ended and one to assume
- that it continues). If a marker doesn't fit any longer it's
- removed and if all of them are gone the pattern mismatches.
- OTOH if any of the markers reaches the end of both the string
- and the pattern simultaneously the pattern matches the string.
- */
- STRPTR s;
- LONG match=0;
- struct markerarray ma, *macur=&ma, *cur2;
- LONG macnt=0, cnt2;
- ULONG level;
- UBYTE a, b, c, t;
- LONG error;
- #define ERROR(a) { error=(a); goto end; }
-
- ma.next=ma.prev=NULL;
- for(;;)
- switch(*pat)
- {
- case MP_MULT: /* _#(_a) */
- /* Split the marker */
- PUSH(0,++pat,str);
- level=1;
- for(;;)
- {
- c=*pat++;
- if(c==MP_MULT)
- level++;
- else if(c==MP_MULT_END)
- if(!--level)
- break;
- }
- break;
- case MP_MULT_END: /* #(a_)_ */
- /* Go back to the start of the block */
- level=1;
- for(;;)
- {
- c=*--pat;
- if(c==MP_MULT_END)
- level++;
- else if(c==MP_MULT)
- if(!--level)
- break;
- }
- break;
- case MP_NOT: /* _~(_a) */
- s=++pat;
- level=1;
- for(;;)
- {
- c=*s++;
- if(c==MP_NOT)
- level++;
- else if(c==MP_NOT_END)
- if(!--level)
- break;
- }
- PUSH(1,s,str);
- break;
- case MP_NOT_END: /* ~(a_)_ */
- cnt2=macnt;
- cur2=macur;
- do
- {
- cnt2--;
- if(cnt2<0)
- {
- cnt2=127;
- cur2=cur2->prev;
- }
- }while(!cur2->marker[cnt2].type);
- if(!*str++)
- {
- macnt=cnt2;
- macur=cur2;
- }else
- if(str>cur2->marker[cnt2].str)
- cur2->marker[cnt2].str=str;
- POP(t,pat,str);
- if(t&&*str)
- { PUSH(1,pat,str+1); }
- break;
- case MP_OR: /* ( */
- s=++pat;
- level=1;
- for(;;)
- {
- c=*s++;
- if(c==MP_OR)
- level++;
- else if(c==MP_OR_NEXT)
- {
- if(level==1)
- { PUSH(0,s,str); }
- }else if(c==MP_OR_END)
- if(!--level)
- break;
- }
- break;
- case MP_OR_NEXT: /* | */
- pat++;
- level=1;
- for(;;)
- {
- c=*pat++;
- if(c==MP_OR)
- level++;
- else if(c==MP_OR_END)
- if(!--level)
- break;
- }
- break;
- case MP_OR_END: /* ) */
- pat++;
- break;
- case MP_SINGLE: /* ? */
- pat++;
- if(*str)
- str++;
- else
- {
- POP(t,pat,str);
- if(t&&*str)
- { PUSH(1,pat,str+1); }
- }
- break;
- case MP_SET: /* [ */
- pat++;
- for(;;)
- {
- a=b=*pat++;
- if(a==MP_SET_END)
- {
- POP(t,pat,str);
- if(t&&*str)
- { PUSH(1,pat,str+1); }
- break;
- }
- if(a==MP_ESCAPE)
- a=b=*pat++ +0x80;
- else if(a==MP_DASH)
- {
- a=*pat++;
- if(a==MP_ESCAPE)
- a=*pat++ +0x80;
- b=*pat++;
- if(b==MP_ESCAPE)
- b=*pat++ +0x80;
- }
- if(*str>=a&&*str<=b)
- {
- str++;
- while(*pat++!=MP_SET_END)
- ;
- break;
- }
- }
- break;
- case MP_NOT_SET: /* [~ */
- if(!*str)
- {
- POP(t,pat,str);
- if(t&&*str)
- { PUSH(1,pat,str+1); }
- break;
- }
- pat++;
- for(;;)
- {
- a=b=*pat++;
- if(a==MP_SET_END)
- {
- str++;
- break;
- }
- if(a==MP_ESCAPE)
- a=b=*pat++ +0x80;
- else if(a==MP_DASH)
- {
- a=*pat++;
- if(a==MP_ESCAPE)
- a=*pat++ +0x80;
- b=*pat++;
- if(b==MP_ESCAPE)
- b=*pat++ +0x80;
- }
- if(*str>=a&&*str<=b)
- {
- POP(t,pat,str);
- if(t&&*str)
- { PUSH(1,pat,str+1); }
- break;
- }
- }
- break;
- case MP_ALL: /* #? */
- /* This often used pattern has extra treatment to be faster */
- if(*str)
- { PUSH(0,pat,str+1); }
- pat++;
- break;
- case 0:
- if(!*str)
- {
- match=1;
- ERROR(0);
- }else
- {
- POP(t,pat,str);
- if(t&&*str)
- { PUSH(1,pat,str+1); }
- }
- break;
- case MP_ESCAPE:
- pat++;
- if(0x80+*pat++==*str)
- str++;
- else
- {
- POP(t,pat,str);
- if(t&&*str)
- { PUSH(1,pat,str+1); }
- }
- break;
- default:
- if(*pat++==*str)
- str++;
- else
- {
- POP(t,pat,str);
- if(t&&*str)
- { PUSH(1,pat,str+1); }
- }
- break;
- }
- end:
- macur=ma.next;
- while(macur!=NULL)
- {
- struct markerarray *next=macur->next;
- FreeMem(macur,sizeof(struct markerarray));
- macur=next;
- }
- ((struct Process *)FindTask(NULL))->pr_Result2=error;
- return match;
- __AROS_FUNC_EXIT
- } /* MatchPattern */
-